PackageId,
Summary
};
+use core::package_id::Metadata;
use core::dependency::SerializedDependency;
use util::{CargoResult, human};
BinTarget
}
-#[deriving(Clone, Hash, PartialEq)]
+#[deriving(Encodable, Decodable, Clone, Hash, PartialEq)]
pub struct Profile {
env: String, // compile, test, dev, bench, etc.
opt_level: uint,
debug: bool,
test: bool,
- dest: Option<String>
+ dest: Option<String>,
}
impl Profile {
pub struct Target {
kind: TargetKind,
name: String,
- path: Path,
- profile: Profile
+ src_path: Path,
+ profile: Profile,
+ metadata: Option<Metadata>
}
#[deriving(Encodable)]
pub struct SerializedTarget {
kind: Vec<&'static str>,
name: String,
- path: String
+ src_path: String,
+ profile: Profile,
+ metadata: Option<Metadata>
}
impl<E, S: Encoder<E>> Encodable<S, E> for Target {
SerializedTarget {
kind: kind,
name: self.name.clone(),
- path: self.path.display().to_str()
+ src_path: self.src_path.display().to_str(),
+ profile: self.profile.clone(),
+ metadata: self.metadata.clone()
}.encode(s)
}
}
impl Show for Target {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}(name={}, path={})", self.kind, self.name,
- self.path.display())
+ self.src_path.display())
}
}
+
impl Manifest {
pub fn new(summary: &Summary, targets: &[Target],
target_dir: &Path, sources: Vec<SourceId>,
impl Target {
pub fn lib_target(name: &str, crate_targets: Vec<LibKind>,
- path: &Path, profile: &Profile) -> Target {
+ src_path: &Path, profile: &Profile,
+ metadata: &Metadata)
+ -> Target
+ {
Target {
kind: LibTarget(crate_targets),
name: name.to_str(),
- path: path.clone(),
- profile: profile.clone()
+ src_path: src_path.clone(),
+ profile: profile.clone(),
+ metadata: Some(metadata.clone())
}
}
- pub fn bin_target(name: &str, path: &Path, profile: &Profile) -> Target {
+ pub fn bin_target(name: &str, src_path: &Path, profile: &Profile) -> Target {
Target {
kind: BinTarget,
name: name.to_str(),
- path: path.clone(),
- profile: profile.clone()
+ src_path: src_path.clone(),
+ profile: profile.clone(),
+ metadata: None
}
}
self.name.as_slice()
}
- pub fn get_path<'a>(&'a self) -> &'a Path {
- &self.path
+ pub fn get_src_path<'a>(&'a self) -> &'a Path {
+ &self.src_path
}
pub fn is_lib(&self) -> bool {
&self.profile
}
+ pub fn get_metadata<'a>(&'a self) -> Option<&'a Metadata> {
+ self.metadata.as_ref()
+ }
+
pub fn rustc_crate_types(&self) -> Vec<&'static str> {
match self.kind {
LibTarget(ref kinds) => {
Decoder
};
-use util::{CargoResult, CargoError};
+use util::{CargoResult, CargoError, short_hash};
use core::source::SourceId;
trait ToVersion {
}
}
-#[deriving(Clone,PartialEq)]
+#[deriving(Clone, PartialEq)]
pub struct PackageId {
name: String,
version: semver::Version,
fn is_human(&self) -> bool { true }
}
+#[deriving(PartialEq, Hash, Clone, Encodable)]
+pub struct Metadata {
+ pub metadata: String,
+ pub extra_filename: String
+}
+
impl PackageId {
pub fn new<T: ToVersion>(name: &str, version: T,
sid: &SourceId) -> CargoResult<PackageId> {
pub fn get_source_id<'a>(&'a self) -> &'a SourceId {
&self.source_id
}
+
+ pub fn generate_metadata(&self) -> Metadata {
+ let metadata = format!("{}:-:{}:-:{}", self.name, self.version, self.source_id);
+ let extra_filename = short_hash(
+ &(self.name.as_slice(), self.version.to_str(), &self.source_id));
+
+ Metadata { metadata: metadata, extra_filename: extra_filename }
+ }
}
static central_repo: &'static str = "http://rust-lang.org/central-repo";
fn fingerprint(&self, pkg: &Package) -> CargoResult<String>;
}
-#[deriving(Encodable, Decodable, Show, Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[deriving(Encodable, Decodable, Show, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SourceKind {
/// GitKind(<git reference>) represents a git repository
GitKind(String),
RegistryKind
}
-#[deriving(Clone, PartialEq, Eq)]
+#[deriving(Clone, PartialEq, Eq, Hash)]
pub enum Location {
Local(Path),
Remote(Url),
}
}
-#[deriving(Encodable, Decodable, Clone, Eq)]
+#[deriving(Encodable, Decodable, Clone, Eq, Hash)]
pub struct SourceId {
pub kind: SourceKind,
pub location: Location,
// TODO: Figure out how this works with targets
let fingerprint_loc = cx.dest.join(format!(".{}.fingerprint",
pkg.get_name()));
+
let (is_fresh, fingerprint) = try!(is_fresh(pkg, &fingerprint_loc, cx,
targets));
.env("RUST_LOG", None) // rustc is way too noisy
}
-fn build_base_args(into: &mut Args, target: &Target, crate_types: Vec<&str>,
- cx: &Context) {
+fn build_base_args(into: &mut Args,
+ target: &Target,
+ crate_types: Vec<&str>,
+ cx: &Context)
+{
+ let metadata = target.get_metadata();
+
// TODO: Handle errors in converting paths into args
- into.push(target.get_path().display().to_str());
+ into.push(target.get_src_path().display().to_str());
into.push("--crate-name".to_str());
into.push(target.get_name().to_str());
into.push("--test".to_str());
}
+ match metadata {
+ Some(m) => {
+ into.push("-C".to_str());
+ into.push(format!("metadata={}", m.metadata));
+
+ into.push("-C".to_str());
+ into.push(format!("extra-filename={}", m.extra_filename));
+ }
+ None => {}
+ }
+
if target.is_lib() {
into.push("--out-dir".to_str());
into.push(out.display().to_str());
use std::io::MemWriter;
+use std::hash::{Hasher, Hash};
+use std::hash::sip::SipHasher;
use serialize::hex::ToHex;
writer.get_ref().to_hex()
}
+pub fn short_hash<H: Hash>(hashable: &H) -> String {
+ let hasher = SipHasher::new_with_keys(0, 0);
+ to_hex(hasher.hash(hashable))
+}
pub use self::errors::{CliError, FromError, ProcessError};
pub use self::errors::{process_error, internal_error, internal, human};
pub use self::paths::realpath;
-pub use self::hex::to_hex;
+pub use self::hex::{to_hex, short_hash};
pub use self::pool::TaskPool;
pub use self::dependency_queue::{DependencyQueue, Fresh, Dirty, Freshness};
use core::{SourceId, GitKind};
use core::manifest::{LibKind, Lib, Profile};
use core::{Summary, Manifest, Target, Dependency, PackageId};
+use core::package_id::Metadata;
use core::source::Location;
use util::{CargoResult, Require, human};
human("No `package` or `project` section found.")
}));
+ let pkgid = try!(project.to_package_id(source_id));
+ let metadata = pkgid.generate_metadata();
// If we have no lib at all, use the inferred lib if available
// If we have a lib with a path, we're done
// Get targets
let targets = normalize(lib.as_ref().map(|l| l.as_slice()),
- bins.as_ref().map(|b| b.as_slice()));
+ bins.as_ref().map(|b| b.as_slice()),
+ &metadata);
if targets.is_empty() {
debug!("manifest has no build targets; project={}", self.project);
try!(process_dependencies(&mut cx, true, self.dev_dependencies.as_ref()));
}
- let pkgid = try!(project.to_package_id(source_id));
let summary = Summary::new(&pkgid, deps.as_slice());
Ok((Manifest::new(
&summary,
}
fn normalize(lib: Option<&[TomlLibTarget]>,
- bin: Option<&[TomlBinTarget]>)
+ bin: Option<&[TomlBinTarget]>,
+ metadata: &Metadata)
-> Vec<Target>
{
log!(4, "normalizing toml targets; lib={}; bin={}", lib, bin);
ret
}
- fn lib_targets(dst: &mut Vec<Target>, libs: &[TomlLibTarget]) {
+ fn lib_targets(dst: &mut Vec<Target>, libs: &[TomlLibTarget], metadata: &Metadata) {
let l = &libs[0];
let path = l.path.clone().unwrap_or_else(|| format!("src/{}.rs", l.name));
let crate_types = l.crate_type.clone().and_then(|kinds| {
for profile in target_profiles(l).iter() {
dst.push(Target::lib_target(l.name.as_slice(), crate_types.clone(),
- &Path::new(path.as_slice()), profile));
+ &Path::new(path.as_slice()), profile,
+ metadata));
}
}
for profile in target_profiles(bin).iter() {
dst.push(Target::bin_target(bin.name.as_slice(),
- &Path::new(path.as_slice()), profile));
+ &Path::new(path.as_slice()),
+ profile));
}
}
}
match (lib, bin) {
(Some(ref libs), Some(ref bins)) => {
- lib_targets(&mut ret, libs.as_slice());
+ lib_targets(&mut ret, libs.as_slice(), metadata);
bin_targets(&mut ret, bins.as_slice(),
|bin| format!("src/bin/{}.rs", bin.name));
},
(Some(ref libs), None) => {
- lib_targets(&mut ret, libs.as_slice());
+ lib_targets(&mut ret, libs.as_slice(), metadata);
},
(None, Some(ref bins)) => {
bin_targets(&mut ret, bins.as_slice(),